#include "smartingimpedancemeter.h"

#include <QtQml>
#include <QDebug>

#define REFRESH_INTERVAL 125

SmartingImpedanceMeter::SmartingImpedanceMeter(QQuickItem *parent) : QQuickItem(parent)
{
    this->setFlag(ItemHasContents);

    QQmlEngine engine;
    QQmlComponent component(&engine);

    component.setData("import QtQuick 2.0\n"
                      "Rectangle"
                      "{"
                      "color: 'green';"
                      "width: 30;"
                      "height: width;"
                      "radius: 0.5 * width;"
                      "}", QUrl());

    if(component.status() != component.Ready)
    {
        qDebug() << "ERROR: " + component.errorString();
    }

    QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
    item->setParentItem(this);
}

void SmartingImpedanceMeter::registerTypes(const char *uri)
{
    qmlRegisterType<SmartingImpedanceMeter>(uri, 1, 0, "SmartingImpedanceMeter");
}

bool SmartingImpedanceMeter::init(int burstLength)
{
    _burstLength = burstLength;

    _lowPass = new ButterFilter();
    _lowPass->init(4, burstLength);
    _lowPass->setCoefficients(0.26, ButterFilter::LOWPASS);

    _highPass = new ButterFilter();
    _highPass->init(4, burstLength);
    _highPass->setCoefficients(0.24, ButterFilter::HIGHPASS);

    _internalISig = new ISignal(4, burstLength);

    _inISig = (ISignal *) _lowPass->getISignal();
    SignalConnection::connect(_lowPass->getOSignal(), _highPass->getISignal());
    SignalConnection::connect(_highPass->getOSignal(), _internalISig);

    _workerThread = new QThread(this);
    _workerThread->start();

    _worker = new SmartingImpedanceMeterWorker(*this);
    _worker->moveToThread(_workerThread);

    return true;
}

bool SmartingImpedanceMeter::start()
{
    QMetaObject::invokeMethod(_worker, "_start", Qt::QueuedConnection);
    return true;
}

SmartingImpedanceMeterWorker::SmartingImpedanceMeterWorker(SmartingImpedanceMeter &context) : QObject(0), _context(context)
{
}

void SmartingImpedanceMeterWorker::_start()
{
    int &burstLength = _context._burstLength;
    ISignal &inISig = *_context._internalISig;

    float &thresholdLow = _context._thresholdLow;
    float &thresholdHigh = _context._thresholdHigh;
    SmartingImpedanceMeter::impedanceValue &prevImpedance = _context._prevImpedance;
    int &refreshInterval = _context._refreshInterval;

    sample_t impedance = 0;

    sample_t rePart = 0;
    sample_t imPart = 0;

    while(inISig.requestBurst(burstLength))
    {
        for(int i = 0; i < burstLength; ++i)
        {
            inISig.readInSample();
        }
        refreshInterval += burstLength;

        if(refreshInterval > REFRESH_INTERVAL)
        {
            refreshInterval = 0;

            rePart = inISig[3] - inISig[1];
            rePart *= rePart;

            imPart = inISig[2] - inISig[0];
            imPart *= imPart;

            impedance = sqrt((rePart + imPart) / 4);

            if(impedance < thresholdLow)
            {
                if(prevImpedance != SmartingImpedanceMeter::LOW)
                {
                    prevImpedance = SmartingImpedanceMeter::LOW;
                    _context.childItems().at(0)->setProperty("color", QVariant("green"));
                }
            }else if(impedance < thresholdHigh)
            {
                if(prevImpedance != SmartingImpedanceMeter::MEDIUM)
                {
                    prevImpedance = SmartingImpedanceMeter::MEDIUM;
                    _context.childItems().at(0)->setProperty("color", QVariant("orange"));
                }
            }else
            {
                if(prevImpedance != SmartingImpedanceMeter::HIGH)
                {
                    prevImpedance = SmartingImpedanceMeter::HIGH;
                    _context.childItems().at(0)->setProperty("color", QVariant("red"));
                }
            }
        }
    }
}
